package org.darkforest.common.wxpay.utils;


import net.sf.json.JSONObject;
import org.darkforest.enums.SettingNameEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import java.io.*;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

public class HttpTool {

    //得到用户access_token,openid等信息
    public final static String get_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    //得到用户详细信息 2.0认证方式
    public final static String oauth_info = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";

    //根据UnionID机制获得用户详细信息
    public final static String unionID_info = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";

    public final static String get_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

    public final static String refund_url = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    // 企业微信
    public final static String get_qy_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=APPID&corpsecret=SECRET";
    public final static String get_qy_userInfo_url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";
    public final static String get_qy_ticket_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN";
    public final static String get_userid_to_openid_url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token=ACCESS_TOKEN";


    public static String getToken(String appid, String appsecret, String grantType, String code) {
        String requestUrl = get_token_url.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code).replace("authorization_code", grantType);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.toString();
    }

    public static String getUserDetail(String access_token, String openid) {
        String requestUrl = oauth_info.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.toString();
    }

    public static String getJsTicket(String access_token) {
        String requestUrl = get_ticket_url.replace("ACCESS_TOKEN", access_token);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.get("ticket").toString();
    }

    public static String getUserDetailByUUnionID(String access_token, String openid) {
        String requestUrl = unionID_info.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.toString();
    }

    public static String getQyToken(String appid, String appsecret, String code) {

        Logger logger = LoggerFactory.getLogger(HttpTool.class);

        System.out.println("appid="+appid+"---appsecret="+appsecret+"--code="+code);

        // 取得access_token
        String requestUrl = get_qy_token_url.replace("APPID", appid).replace("SECRET", appsecret);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        String accessToken = jsonObject.getString("access_token");

        // 取得UserId
        requestUrl = get_qy_userInfo_url.replace("ACCESS_TOKEN", accessToken).replace("CODE", code);
        jsonObject = httpRequest(requestUrl, "GET", null);

        String openId = null;
        //  非企业成员授权时返回OpenId
        // 企业成员授权时返回UserId
        if (jsonObject.containsKey("UserId")) {
            String userId = jsonObject.getString("UserId");
            requestUrl = get_userid_to_openid_url.replace("ACCESS_TOKEN", accessToken);
            //String param = "{\\\"userid\\\": \\\"zhangsan\\\"} ";
            String param = "{\"userid\": \"" + userId + "\"}";
            jsonObject = httpRequest(requestUrl, "GET", param);
            openId = jsonObject.getString("openid");

            logger.info("===== jsonObject：" + jsonObject.toString() + "=====");
        } else {
            openId = jsonObject.getString("OpenId");
        }

        System.out.println("access_token="+accessToken+"---openid="+openId);

        JSONObject jsonObj = new JSONObject();
        jsonObj.put("access_token", accessToken);
        jsonObj.put("openid", openId);

        System.out.println("jsonObj="+jsonObj.toString());

        return jsonObj.toString();
    }

    public static String getQYJsTicket(String access_token) {
        String requestUrl = get_qy_ticket_url.replace("ACCESS_TOKEN", access_token);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.get("ticket").toString();
    }

    /**
     * 使用Get方式获取数据
     *
     * @param url     URL包括参数，http://HOST/XX?XX=XX&XXX=XXX
     * @param charset
     * @return
     */
    public static String sendGet(String url, String charset) {
        String result = "";
        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream(), charset));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * POST请求，字符串形式数据
     *
     * @param url     请求地址
     * @param param   请求数据
     * @param charset 编码方式
     */
    public static String sendPostUrl(String url, String param, String charset) {

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * POST请求，Map形式数据
     *
     * @param url     请求地址
     * @param param   请求数据
     * @param charset 编码方式
     */
    public static String sendPost(String url, Map<String, String> param, String charset) {

        StringBuffer buffer = new StringBuffer();
        buffer.append("<xml>");
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, String> entry : param.entrySet()) {
                if (entry.getKey().equals("attach") || entry.getKey().equals("body") || entry.getKey().equals("sign")) {
                    buffer.append("<" + entry.getKey() + ">");
                    buffer.append("<![CDATA[" + entry.getValue() + "]]>");
                    buffer.append("</" + entry.getKey() + ">");
                } else {
                    buffer.append("<" + entry.getKey() + ">");
                    buffer.append(entry.getValue());
                    buffer.append("</" + entry.getKey() + ">");
                }
            }
        }
        buffer.append("</xml>");
//        System.out.println(buffer.toString() + "支付XML报文");
//        String xmlString="";
//        try {
//            xmlString = new String(buffer.toString().getBytes(), "utf-8");
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//        System.out.print("xmlString============"+xmlString);
        OutputStreamWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);

            conn.setUseCaches(false); // Post 请求不能使用缓存

            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), charset);
            // 发送请求参数
            out.write(buffer.toString());
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // /1、解决https请求的问题
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);

            // /2、兼容GET、POST两种方式
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpUrlConn.connect();
            }

            // /3、兼容有数据提交、无数据提交两种情况
            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }


    /**
     * 发送json类型参数的post请求
     *
     * @param url
     * @param charset
     * @param param     json字符串类型
     * @param returnStr 返回字段数组
     * @return
     */
    public static String[] sendJsonParamPost(String url, String param, String returnStr[], String charset) {
        String result = HttpTool.sendPostUrl(url, param, charset);
        JSONObject jsonObject = JSONObject.fromObject(result);
        String[] res = new String[returnStr.length];
        for (int i = 0; i < returnStr.length; i++) {
            res[i] = jsonObject.getString(returnStr[i]);
        }
        return res;
    }

    /**
     * 封装一下sendGet方法
     *
     * @param url
     * @param returnStr
     * @return
     */
    public static String[] sendGet(String url, String returnStr[], String charset) {
        String result = HttpTool.sendGet(url, charset);
//        System.out.print("=========="+result);
        JSONObject jsonObject = JSONObject.fromObject(result);
        String[] res = new String[returnStr.length];
        for (int i = 0; i < returnStr.length; i++) {
            res[i] = jsonObject.getString(returnStr[i]);
        }
        return res;
    }

    /**
     * 开启urlConnection读取远程文件到本地
     *
     * @param url
     * @param localPath
     * @throws IOException
     */
    public static void getRemoteFile(String url, String localPath) throws Exception {
        File f = new File(localPath);
        HttpURLConnection httpUrl = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {

            URL urlFile = new URL(url);
            httpUrl = (HttpURLConnection) urlFile.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            bos = new BufferedOutputStream(new FileOutputStream(f));
            int len = 1024;
            byte[] b = new byte[len];
            while ((len = bis.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            bos.flush();
            bis.close();
            httpUrl.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                bis.close();
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
//        return f;
    }

    public static String sendPostMessage(String url, String param,
                                         String charset) {


        OutputStreamWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);

            conn.setDoInput(true);

            conn.setUseCaches(false); // Post 请求不能使用缓存

            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            String encode = "utf-8";


            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), encode);
            // 发送请求参数
            out.write(param.toString());
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    conn.getInputStream(), charset));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
}